home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / dejagnu.lha / dejagnu-1.0.1 / tcl / tclAssem.c < prev    next >
C/C++ Source or Header  |  1993-02-14  |  6KB  |  234 lines

  1. /* 
  2.  * tclAssem.c --
  3.  *
  4.  *    This file contains procedures to help assemble Tcl commands
  5.  *    from an input source  where commands may arrive in pieces, e.g.
  6.  *    several lines of type-in corresponding to one command.
  7.  *
  8.  * Copyright 1990-1991 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #include "tclInt.h"
  19.  
  20. /*
  21.  * The structure below is the internal representation for a command
  22.  * buffer, which is used to hold a piece of a command until a full
  23.  * command is available.  When a full command is available, it will
  24.  * be returned to the user, but it will also be retained in the buffer
  25.  * until the NEXT call to Tcl_AssembleCmd, at which point it will be
  26.  * removed.
  27.  */
  28.  
  29. typedef struct {
  30.     char *buffer;        /* Storage for command being assembled.
  31.                  * Malloc-ed, and grows as needed. */
  32.     int bufSize;        /* Total number of bytes in buffer. */
  33.     int bytesUsed;        /* Number of bytes in buffer currently
  34.                  * occupied (0 means there is not a
  35.                  * buffered incomplete command). */
  36. } CmdBuf;
  37.  
  38. /*
  39.  * Default amount of space to allocate in command buffer:
  40.  */
  41.  
  42. #define CMD_BUF_SIZE 100
  43.  
  44. /*
  45.  *----------------------------------------------------------------------
  46.  *
  47.  * Tcl_CreateCmdBuf --
  48.  *
  49.  *    Allocate and initialize a command buffer.
  50.  *
  51.  * Results:
  52.  *    The return value is a token that may be passed to
  53.  *    Tcl_AssembleCmd and Tcl_DeleteCmdBuf.
  54.  *
  55.  * Side effects:
  56.  *    Memory is allocated.
  57.  *
  58.  *----------------------------------------------------------------------
  59.  */
  60.  
  61. Tcl_CmdBuf
  62. Tcl_CreateCmdBuf()
  63. {
  64.     register CmdBuf *cbPtr;
  65.  
  66.     cbPtr = (CmdBuf *) ckalloc(sizeof(CmdBuf));
  67.     cbPtr->buffer = (char *) ckalloc(CMD_BUF_SIZE);
  68.     cbPtr->buffer[0] = '\0';
  69.     cbPtr->bufSize = CMD_BUF_SIZE;
  70.     cbPtr->bytesUsed = 0;
  71.     return (Tcl_CmdBuf) cbPtr;
  72. }
  73.  
  74. /*
  75.  *----------------------------------------------------------------------
  76.  *
  77.  * Tcl_DeleteCmdBuf --
  78.  *
  79.  *    Release all of the resources associated with a command buffer.
  80.  *    The caller should never again use buffer again.
  81.  *
  82.  * Results:
  83.  *    None.
  84.  *
  85.  * Side effects:
  86.  *    Memory is released.
  87.  *
  88.  *----------------------------------------------------------------------
  89.  */
  90.  
  91. void
  92. Tcl_DeleteCmdBuf(buffer)
  93.     Tcl_CmdBuf buffer;        /* Token for command buffer (return value
  94.                  * from previous call to Tcl_CreateCmdBuf). */
  95. {
  96.     register CmdBuf *cbPtr = (CmdBuf *) buffer;
  97.  
  98.     ckfree(cbPtr->buffer);
  99.     ckfree((char *) cbPtr);
  100. }
  101.  
  102. /*
  103.  *----------------------------------------------------------------------
  104.  *
  105.  * Tcl_AssembleCmd --
  106.  *
  107.  *    This is a utility procedure to assist in situations where
  108.  *    commands may be read piece-meal from some input source.  Given
  109.  *    some input text, it adds the text to an input buffer and returns
  110.  *    whole commands when they are ready.
  111.  *
  112.  * Results:
  113.  *    If the addition of string to any currently-buffered information
  114.  *    results in one or more complete Tcl commands, then the return value
  115.  *    is a pointer to the complete command(s).  The command value will
  116.  *    only be valid until the next call to this procedure with the
  117.  *    same buffer.  If the addition of string leaves an incomplete
  118.  *    command at the end of the buffer, then NULL is returned.
  119.  *
  120.  * Side effects:
  121.  *    If string leaves a command incomplete, the partial command
  122.  *    information is buffered for use in later calls to this procedure.
  123.  *    Once a command has been returned, that command is deleted from
  124.  *    the buffer on the next call to this procedure.
  125.  *
  126.  *----------------------------------------------------------------------
  127.  */
  128.  
  129. char *
  130. Tcl_AssembleCmd(buffer, string)
  131.     Tcl_CmdBuf buffer;        /* Token for a command buffer previously
  132.                  * created by Tcl_CreateCmdBuf.  */
  133.     char *string;        /* Bytes to be appended to command stream.
  134.                  * Note:  if the string is zero length,
  135.                  * then whatever is buffered will be
  136.                  * considered to be a complete command
  137.                  * regardless of whether parentheses are
  138.                  * matched or not. */
  139. {
  140.     register CmdBuf *cbPtr = (CmdBuf *) buffer;
  141.     int length, totalLength, c;
  142.  
  143.     /*
  144.      * If an empty string is passed in, just pretend the current
  145.      * command is complete, whether it really is or not.
  146.      */
  147.  
  148.     length = strlen(string);
  149.     if (length == 0) {
  150.     cbPtr->buffer[cbPtr->bytesUsed] = 0;
  151.     cbPtr->bytesUsed = 0;
  152.     return cbPtr->buffer;
  153.     }
  154.  
  155.     /*
  156.      * Add the new information to the buffer.  If the current buffer
  157.      * isn't large enough, grow it by at least a factor of two, or
  158.      * enough to hold the new text.
  159.      */
  160.  
  161.     length = strlen(string);
  162.     totalLength = cbPtr->bytesUsed + length + 1;
  163.     if (totalLength > cbPtr->bufSize) {
  164.     unsigned int newSize;
  165.     char *newBuf;
  166.  
  167.     newSize = cbPtr->bufSize*2;
  168.     if (newSize < totalLength) {
  169.         newSize = totalLength;
  170.     }
  171.     newBuf = (char *) ckalloc(newSize);
  172.     strcpy(newBuf, cbPtr->buffer);
  173.     ckfree(cbPtr->buffer);
  174.     cbPtr->buffer = newBuf;
  175.     cbPtr->bufSize = newSize;
  176.     }
  177.     strcpy(cbPtr->buffer+cbPtr->bytesUsed, string);
  178.     cbPtr->bytesUsed += length;
  179.  
  180.     /*
  181.      * See if there is now a complete command in the buffer.
  182.      */
  183.  
  184.     c = cbPtr->buffer[cbPtr->bytesUsed-1];
  185.     if ((c != '\n') && (c != ';')) {
  186.     return NULL;
  187.     }
  188.     if (Tcl_CommandComplete(cbPtr->buffer)) {
  189.     cbPtr->bytesUsed = 0;
  190.     return cbPtr->buffer;
  191.     }
  192.     return NULL;
  193. }
  194.  
  195. /*
  196.  *----------------------------------------------------------------------
  197.  *
  198.  * Tcl_CommandComplete --
  199.  *
  200.  *    Given a partial or complete Tcl command, this procedure
  201.  *    determines whether the command is complete in the sense
  202.  *    of having matched braces and quotes and brackets.
  203.  *
  204.  * Results:
  205.  *    1 is returned if the command is complete, 0 otherwise.
  206.  *
  207.  * Side effects:
  208.  *    None.
  209.  *
  210.  *----------------------------------------------------------------------
  211.  */
  212.  
  213. int
  214. Tcl_CommandComplete(cmd)
  215.     char *cmd;            /* Command to check. */
  216. {
  217.     register char *p = cmd;
  218.  
  219.     p = cmd;
  220.     while (1) {
  221.     while (isspace(*p)) {
  222.         p++;
  223.     }
  224.     if (*p == 0) {
  225.         return 1;
  226.     }
  227.     p = TclWordEnd(p, 0);
  228.     if (*p == 0) {
  229.         return 0;
  230.     }
  231.     p++;
  232.     }
  233. }
  234.